﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace TasksUI.Controls
{
    public partial class TaskListControl : UserControl
    {
        public TaskListControl()
        {
            InitializeComponent();
            Disposed += new EventHandler(TaskListControl_Disposed);
        }

        private void TaskListControl_Disposed(object sender, EventArgs e)
        {
            if (_taskList != null)
                _taskList.CollectionChanged -= new System.Collections.Specialized.NotifyCollectionChangedEventHandler(_taskList_CollectionChanged);
        }

        private TasksModel.TaskList _taskList;

        [DefaultValue(null)]
        public TasksModel.TaskList TaskList
        {
            [System.Diagnostics.DebuggerStepThrough]
            get { return _taskList; }
            set
            {
                if (value == null)
                    return;
                if (_taskList != null)
                    _taskList.CollectionChanged -= new System.Collections.Specialized.NotifyCollectionChangedEventHandler(_taskList_CollectionChanged);
                _taskList = value;
                _taskList.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(_taskList_CollectionChanged);
                RefreshView();
            }
        }

        [DefaultValue(false)]
        public bool ReadOnly { get; set; }

        private void RefreshView()
        {
            if (Tag != null)
                return;// sentinel
            Tag = this;
            try
            {
                SuspendLayout();
                Controls.Clear();
                for (int i = 0; i < _taskList.Count; i++)
                {
                    TasksModel.Task t = _taskList[i];
                    AddTask(t);
                }
                ResumeLayout(true);
            }
            finally
            {
                Tag = null;
            }
        }

        private void _taskList_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
            {
                foreach (Control c in Controls)
                    if (((TaskControl)c).Task.ID == ((TasksModel.Task)e.OldItems[0]).ID)
                    {
                        Controls.Remove(c);
                        break;
                    }
                return;
            }
            RefreshView();
        }

        public TaskControl AddTask(TasksModel.Task task)
        {
            Tag = this;
            try
            {
                TaskControl tc = new TaskControl();
                tc.Task = task;
                tc.TaskList = this;
                tc.TabIndex = _taskList.Count;
                tc.Dock = DockStyle.Top;
                tc.ReadOnly = ReadOnly;
                // controls are sorted in reverse order
                Controls.Add(tc);
                Controls.SetChildIndex(tc, 0);
                return tc;
            }
            finally
            {
                Tag = null;
            }
        }

        private void TaskListControl_DragDrop(object sender, DragEventArgs e)
        {
            TaskControl tc = e.Data.GetData(
                typeof(TaskControl)) as TaskControl;
            if (tc != null && !ReadOnly)
            {
                TasksModel.Task t = tc.Task as TasksModel.Task;
                if (t != null)
                {
                    if (tc.TaskList == this)
                    {
                        // change order
                        Point p = PointToClient(new Point(e.X, e.Y));
                        Control c = GetChildAtPoint(p, GetChildAtPointSkip.Invisible);
                        if (c == null)
                        {
                            // move to the end of the list
                            Tag = this;
                            try
                            {
                                Controls.SetChildIndex(tc, 0);
                                TaskList.MoveToTheEnd(tc.Task);
                            }
                            finally
                            {
                                Tag = null;
                            }
                        }
                        else
                        {
                            Tag = this;
                            try
                            {
                                // move before the control the mouse is over
                                Controls.SetChildIndex(tc, Controls.IndexOf(c));
                                TaskList.MoveTo(tc.Task, (c as TaskControl).Task.Order);
                            }
                            finally
                            {
                                Tag = null;
                            }
                        }
                        tc.TabIndex = Controls.IndexOf(tc);
                        return;
                    }
                    // remove from source list
                    try
                    {
                        tc.TaskList.Remove(tc);
                        // add this task here
                        Tag = this;
                        try
                        {
                            TaskList.Append(t);
                        }
                        finally
                        {
                            Tag = null;
                        }
                        AddTask(t);
                    }
                    catch (Exception ex)
                    {
                        ErrorHandler.ExceptionHandler.HandleException(ex);
                    }
                }
            }
        }

        private void TaskListControl_DragOver(object sender, DragEventArgs e)
        {
            if (!e.Data.GetDataPresent(typeof(TaskControl)) || ReadOnly)
            {
                e.Effect = DragDropEffects.None;
                return;
            }
            e.Effect = DragDropEffects.Move;
        }

        public void BeginDrag(TaskControl taskControl)
        {
            if (!ReadOnly)
                DoDragDrop(taskControl, DragDropEffects.Move);
        }

        [System.Diagnostics.DebuggerStepThrough]
        private void TaskListControl_GiveFeedback(object sender, GiveFeedbackEventArgs e)
        {
            e.UseDefaultCursors = true;
        }

        public void Remove(TaskControl taskControl)
        {
            Controls.Remove(taskControl);
            Tag = this;
            try
            {
                TaskList.RemoveOrderAware(taskControl.Task);
            }
            finally
            {
                Tag = null;
            }
        }

        public void MoveToTop(TaskControl tc)
        {
            Controls.SetChildIndex(tc, Controls.Count - 1);
            TaskList.MoveTo(tc.Task, 0);
        }
    }
}
